package com.hmy.finance.service.core.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hmy.finance.common.enums.PaymentStatusEnum;
import com.hmy.finance.dal.mapper.DeviceDailyBillMapper;
import com.hmy.finance.dal.po.DeviceDailyBillPo;
import com.hmy.finance.dal.po.DeviceRentalRecordPo;
import com.hmy.finance.service.core.IDeviceDailyBillService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.sql.Timestamp;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.List;

/**
 * @author songkf
 * @description 针对表【device_daily_bill(设备日费用账单流水)】的数据库操作Service实现
 * @createDate 2024-02-21 18:55:01
 */
@Service
public class DeviceDailyBillServiceImpl extends ServiceImpl<DeviceDailyBillMapper, DeviceDailyBillPo> implements IDeviceDailyBillService {

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int saveBatchDeviceDailyBill(List<DeviceDailyBillPo> deviceDailyBillPoList) {
        return this.baseMapper.insertBatch(deviceDailyBillPoList);
    }

    @Override
    public DeviceDailyBillPo queryDeviceDailyBillByDeviceRentalRecordIdWithDate(Long deviceRentalRecordId, LocalDate handleDate) {
        LocalDateTime startOfDay = handleDate.atStartOfDay();
        // 将 LocalDateTime 转换为 Timestamp
        Timestamp startTimestamp = Timestamp.valueOf(startOfDay);
        // 计算结束时间（下一天的开始时间，即不包含当天）
        LocalDateTime nextDayStart = handleDate.atTime(LocalTime.MAX);
        // 将结束时间转换为 Timestamp
        Timestamp endTimestamp = Timestamp.valueOf(nextDayStart);
        return this.baseMapper.selectOne(Wrappers.lambdaQuery(DeviceDailyBillPo.class)
                .eq(DeviceDailyBillPo::getDeviceRentalRecordId, deviceRentalRecordId)
                .eq(DeviceDailyBillPo::getFeeStatus, true)
                .between(DeviceDailyBillPo::getFeeIncurredTime, startTimestamp, endTimestamp));
    }

    @Override
    public Boolean clearDeviceDailyBill(List<DeviceRentalRecordPo> rentingDeviceList, LocalDate localDate) {
        // 将 LocalDate 转换为 LocalDateTime，时间设为当天的开始时间（00:00:00）
        LocalDateTime startOfDay = localDate.atStartOfDay();
        return this.update(Wrappers.lambdaUpdate(DeviceDailyBillPo.class).set(DeviceDailyBillPo::getFeeStatus, false).ge(DeviceDailyBillPo::getFeeIncurredTime, startOfDay).in(DeviceDailyBillPo::getDeviceRentalRecordId, rentingDeviceList.stream().map(DeviceRentalRecordPo::getId).toArray()));
    }

    @Override
    public List<DeviceDailyBillPo> queryDeviceDailyBillListByRentalRecordIdAndDateArea(List<Long> deviceRentalRecordIdList, LocalDate localDate, LocalDate now) {
        LambdaQueryWrapper<DeviceDailyBillPo> lambdaQueryWrapper = Wrappers.lambdaQuery(DeviceDailyBillPo.class);
        lambdaQueryWrapper.eq(DeviceDailyBillPo::getFeeStatus, true);
        lambdaQueryWrapper.in(DeviceDailyBillPo::getDeviceRentalRecordId, deviceRentalRecordIdList);
        if (localDate != null && now != null) {
            LocalDateTime startOfDay = localDate.atStartOfDay();
            LocalDateTime endOfDay = now.atTime(LocalTime.MAX);
            lambdaQueryWrapper.between(DeviceDailyBillPo::getFeeIncurredTime, startOfDay, endOfDay);
        }
        return this.list(lambdaQueryWrapper);
    }

    @Override
    public List<DeviceDailyBillPo> queryDeviceDailyBillListByContractIdAndDateArea(Long contractId, LocalDate handleDate, LocalDate handleDate1) {
        LocalDateTime startOfDay = handleDate.atStartOfDay();
        LocalDateTime endOfDay = handleDate1.atTime(LocalTime.MAX);
        return this.list(Wrappers.lambdaQuery(DeviceDailyBillPo.class).eq(DeviceDailyBillPo::getContractId, contractId).between(DeviceDailyBillPo::getFeeIncurredTime, startOfDay, endOfDay).eq(DeviceDailyBillPo::getFeeStatus, true));
    }

    @Override
    public List<DeviceDailyBillPo> queryDeviceDailyBillListByContractIdAndDateArea(List<Long> deviceRentalRecordIdList, LocalDate localDate, LocalDate now) {
        LocalDateTime startOfDay = localDate.atStartOfDay();
        LocalDateTime endOfDay = now.atTime(LocalTime.MAX);
        return this.list(Wrappers.lambdaQuery(DeviceDailyBillPo.class).eq(DeviceDailyBillPo::getFeeStatus, true).in(DeviceDailyBillPo::getDeviceRentalRecordId, deviceRentalRecordIdList).between(DeviceDailyBillPo::getFeeIncurredTime, startOfDay, endOfDay));
    }

    @Override
    public List<DeviceDailyBillPo> selectByContractIdAndOffsetThroughDate(Long contractId, LocalDate startDate, LocalDate endDate) {
        LambdaQueryWrapper<DeviceDailyBillPo> wrapper = Wrappers.lambdaQuery(DeviceDailyBillPo.class)
                .eq(DeviceDailyBillPo::getContractId, contractId)
                .eq(DeviceDailyBillPo::getFeeStatus, true)
                .in(DeviceDailyBillPo::getPaymentStatus, PaymentStatusEnum.UNPAID, PaymentStatusEnum.PARTIAL_PAYMENT)

                .orderByDesc(DeviceDailyBillPo::getFeeIncurredTime);
        if (startDate != null) {
            wrapper.ge(DeviceDailyBillPo::getFeeIncurredTime, startDate.atStartOfDay());
        }
        if (endDate != null) {
            wrapper.le(DeviceDailyBillPo::getFeeIncurredTime, endDate.atTime(LocalTime.MAX));
        }
        return this.baseMapper.selectList(wrapper);
    }

    @Override
    public List<DeviceDailyBillPo> queryDeviceDailyBillByDeviceRentalRecordIdWithDateArea(Long deviceRentalRecordId, LocalDate overdueStartDate, LocalDate overdueEndDate) {
        LocalDateTime startTime = overdueStartDate.atStartOfDay();
        LocalDateTime endTime = overdueEndDate.atTime(LocalTime.MAX);
        return this.baseMapper.selectList(Wrappers.lambdaQuery(DeviceDailyBillPo.class).eq(DeviceDailyBillPo::getDeviceRentalRecordId, deviceRentalRecordId).eq(DeviceDailyBillPo::getFeeStatus, true).between(DeviceDailyBillPo::getFeeIncurredTime, startTime, endTime));
    }
}




